// import com.alibaba.druid.sql.ast.*;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;

// import java.util.Collections;
// import java.util.List;

#include "SQLFlashbackExpr.h"
#include "../SQLName.h"
#include "../../visitor/SQLASTVisitor.h"

SQLFlashbackExpr_Type_ptr SQLFlashbackExpr_Type::SCN = SQLFlashbackExpr_Type_ptr(new SQLFlashbackExpr_Type(1LL << 0, make_string_ptr("SCN")));
SQLFlashbackExpr_Type_ptr SQLFlashbackExpr_Type::TIMESTAMP = SQLFlashbackExpr_Type_ptr(new SQLFlashbackExpr_Type(1LL << 1, make_string_ptr("TIMESTAMP")));

SQLFlashbackExpr_Type::SQLFlashbackExpr_Type(uint64_t mask, string_ptr name)
{
  this->mask = mask;
  this->name = name;
}

SQLFlashbackExpr::SQLFlashbackExpr()
{
}

SQLFlashbackExpr::SQLFlashbackExpr(SQLFlashbackExpr_Type_ptr type, SQLExpr_ptr expr)
{
  this->type = type;
  this->setExpr(expr);
}

SQLFlashbackExpr_Type_ptr SQLFlashbackExpr::getType()
{
  return type;
}

void SQLFlashbackExpr::setType(SQLFlashbackExpr_Type_ptr type)
{
  this->type = type;
}

SQLExpr_ptr SQLFlashbackExpr::getExpr()
{
  return expr;
}

void SQLFlashbackExpr::setExpr(SQLExpr_ptr expr)
{
  if (expr != nullptr)
  {
    expr->setParent(SharedObject(SQLFlashbackExpr));
  }
  this->expr = expr;
}

//@Override
BOOL_ptr SQLFlashbackExpr::replace(SQLExpr_ptr expr, SQLExpr_ptr target)
{
  if (this->expr == expr)
  {
    setExpr(std::dynamic_pointer_cast<SQLName>(target));
    return BOOL::TRUE;
  }
  return BOOL::FALSE;
}

//@Override
void SQLFlashbackExpr::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLFlashbackExpr)))
  {
    if (this->expr != nullptr)
    {
      this->expr->accept(visitor);
    }
  }
  visitor->endVisit(SharedObject(SQLFlashbackExpr));
}

//@Override
SQLObject_list_ptr SQLFlashbackExpr::getChildren()
{
  SQLObject_list_ptr tmp = SQLObject_list_ptr();
  tmp->push_back(expr);
  return tmp;
}

SQLObject_ptr SQLFlashbackExpr::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLFlashbackExpr>(new SQLFlashbackExpr());
  std::shared_ptr<SQLFlashbackExpr> x = std::dynamic_pointer_cast<SQLFlashbackExpr>(clone_tmp);
  // SQLFlashbackExpr x = new SQLFlashbackExpr();
  x->type = this->type;
  if (expr != nullptr)
  {
    x->setExpr(std::dynamic_pointer_cast<SQLExpr>(expr->clone()));
  }
  return x;
}

//@Override
bool SQLFlashbackExpr::equals(Object_ptr o)
{
  if (this == o.get())
  {
    return true;
  }
  if (o == nullptr || getClass() != o->getClass())
  {
    return false;
  }

  std::shared_ptr<SQLFlashbackExpr> that = std::dynamic_pointer_cast<SQLFlashbackExpr>(o);

  if (type != that->type)
  {
    return false;
  }
  return expr != nullptr ? expr->equals(that->expr) : that->expr == nullptr;
}

//@Override
int SQLFlashbackExpr::hashCode()
{
  // int result = type != nullptr ? type->hashCode() : 0;
  int result = (int)type->mask;
  result = 31 * result + (expr != nullptr ? expr->hashCode() : 0);
  return result;
}
